package com.bank.backend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bank.backend.mapper.TradeMapper;
import com.bank.backend.mapper.CardMapper;
import com.bank.backend.model.entity.Trade;
import com.bank.backend.model.entity.Card;
import com.bank.backend.model.entity.User;
import com.bank.backend.model.dto.TradeQueryDTO;
import com.bank.backend.model.dto.TransferDTO;
import com.bank.backend.service.TradeService;
import com.bank.backend.model.vo.TradeVO;
import com.bank.backend.result.PageResult;
import com.bank.backend.utils.UserHolder;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bank.backend.exception.BusinessException;
import com.bank.backend.enums.ErrorCode;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.math.BigDecimal;

import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import cn.hutool.crypto.digest.MD5;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.LocalDate;
import java.util.List;

/**
 * 交易记录业务实现类
 */
@Service
public class TradeServiceImpl extends ServiceImpl<TradeMapper, Trade> implements TradeService {

    private static final Logger log = LoggerFactory.getLogger(TradeServiceImpl.class);

    @Resource
    private CardMapper cardMapper;

    @Override
    public PageResult<TradeVO> queryTradeList(TradeQueryDTO queryDTO) {
        Page<Trade> pageObj = new Page<>(queryDTO.getPage(), queryDTO.getSize());
        LambdaQueryWrapper<Trade> wrapper = new LambdaQueryWrapper<>();
        
        // 卡号查询
        if (queryDTO.getCardId() != null && !queryDTO.getCardId().trim().isEmpty()) {
            wrapper.eq(Trade::getCardId, queryDTO.getCardId().trim());
        }
        
        // 交易类型查询
        if (queryDTO.getTradeType() != null && !queryDTO.getTradeType().trim().isEmpty()) {
            wrapper.eq(Trade::getTradeType, queryDTO.getTradeType().trim());
        }
        
        // 日期范围查询
        if (queryDTO.getStartDate() != null && !queryDTO.getStartDate().trim().isEmpty()) {
            try {
                LocalDate startDate = LocalDate.parse(queryDTO.getStartDate().trim());
                LocalDateTime startDateTime = LocalDateTime.of(startDate, LocalTime.MIN);
                wrapper.ge(Trade::getTradeDate, startDateTime);
            } catch (Exception e) {
                log.warn("Invalid startDate format: {}", queryDTO.getStartDate());
            }
        }
        if (queryDTO.getEndDate() != null && !queryDTO.getEndDate().trim().isEmpty()) {
            try {
                LocalDate endDate = LocalDate.parse(queryDTO.getEndDate().trim());
                LocalDateTime endDateTime = LocalDateTime.of(endDate, LocalTime.MAX);
                wrapper.le(Trade::getTradeDate, endDateTime);
            } catch (Exception e) {
                log.warn("Invalid endDate format: {}", queryDTO.getEndDate());
            }
        }
        
        // 金额范围查询
        if (queryDTO.getMinAmount() != null) {
            wrapper.ge(Trade::getTradeMoney, queryDTO.getMinAmount());
        }
        if (queryDTO.getMaxAmount() != null) {
            wrapper.le(Trade::getTradeMoney, queryDTO.getMaxAmount());
        }
        
        // 备注模糊查询
        if (queryDTO.getRemark() != null && !queryDTO.getRemark().trim().isEmpty()) {
            wrapper.like(Trade::getRemark, queryDTO.getRemark().trim());
        }
        
        wrapper.eq(Trade::getIsDeleted, 0);
        wrapper.orderByDesc(Trade::getTradeDate);
        
        Page<Trade> tradePage = this.page(pageObj, wrapper);
        ArrayList<TradeVO> voList = new ArrayList<>();
        for (Trade trade : tradePage.getRecords()) {
            TradeVO vo = new TradeVO();
            BeanUtils.copyProperties(trade, vo);
            voList.add(vo);
        }
        PageResult<TradeVO> result = new PageResult<>();
        result.setTotal(tradePage.getTotal());
        result.setPage((int) tradePage.getCurrent());
        result.setSize((int) tradePage.getSize());
        result.setRecords(voList);
        return result;
    }

    @Override
    public void deleteTrade(Integer tradeId) {
        Trade trade = this.getById(tradeId);
        if (trade == null || trade.getIsDeleted()==1) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "交易记录不存在");
        }
        LambdaUpdateWrapper<Trade> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Trade::getTradeId, tradeId);
        updateWrapper.set(Trade::getIsDeleted, 1);
        updateWrapper.set(Trade::getUpdateTime, LocalDateTime.now());
        boolean success = this.update(updateWrapper);
        if (!success) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "删除交易记录失败");
        }
    }

    @Override
    public PageResult<TradeVO> pageList(TradeQueryDTO queryDTO) {
        Page<Trade> pageObj = new Page<>(queryDTO.getPage(), queryDTO.getSize());
        LambdaQueryWrapper<Trade> wrapper = new LambdaQueryWrapper<>();
        // 只查当前用户的银行卡
        Integer userId = UserHolder.getUserId();
        if (userId != null) {
            // 查出该用户所有银行卡号
            List<Card> userCards = cardMapper.selectList(new LambdaQueryWrapper<Card>().eq(Card::getUserId, userId).eq(Card::getIsDeleted, 0));
            List<String> cardIds = new ArrayList<>();
            for (Card c : userCards) {
                cardIds.add(c.getCardId());
            }
            if (!cardIds.isEmpty()) {
                wrapper.in(Trade::getCardId, cardIds);
            } else {
                // 没有卡，直接返回空
                PageResult<TradeVO> result = new PageResult<>();
                result.setTotal(0L);
                result.setPage(queryDTO.getPage());
                result.setSize(queryDTO.getSize());
                result.setRecords(new ArrayList<>());
                return result;
            }
        }
        // 卡号查询
        if (queryDTO.getCardId() != null && !queryDTO.getCardId().trim().isEmpty()) {
            wrapper.eq(Trade::getCardId, queryDTO.getCardId().trim());
        }
        // 交易类型查询
        if (queryDTO.getTradeType() != null && !queryDTO.getTradeType().trim().isEmpty()) {
            wrapper.eq(Trade::getTradeType, queryDTO.getTradeType().trim());
        }
        // 日期范围查询
        if (queryDTO.getStartDate() != null && !queryDTO.getStartDate().trim().isEmpty()) {
            try {
                LocalDate startDate = LocalDate.parse(queryDTO.getStartDate().trim());
                LocalDateTime startDateTime = LocalDateTime.of(startDate, LocalTime.MIN);
                wrapper.ge(Trade::getTradeDate, startDateTime);
            } catch (Exception e) {
                log.warn("Invalid startDate format: {}", queryDTO.getStartDate());
            }
        }
        if (queryDTO.getEndDate() != null && !queryDTO.getEndDate().trim().isEmpty()) {
            try {
                LocalDate endDate = LocalDate.parse(queryDTO.getEndDate().trim());
                LocalDateTime endDateTime = LocalDateTime.of(endDate, LocalTime.MAX);
                wrapper.le(Trade::getTradeDate, endDateTime);
            } catch (Exception e) {
                log.warn("Invalid endDate format: {}", queryDTO.getEndDate());
            }
        }
        // 金额范围查询
        if (queryDTO.getMinAmount() != null) {
            wrapper.ge(Trade::getTradeMoney, queryDTO.getMinAmount());
        }
        if (queryDTO.getMaxAmount() != null) {
            wrapper.le(Trade::getTradeMoney, queryDTO.getMaxAmount());
        }
        // 备注模糊查询
        if (queryDTO.getRemark() != null && !queryDTO.getRemark().trim().isEmpty()) {
            wrapper.like(Trade::getRemark, queryDTO.getRemark().trim());
        }
        wrapper.eq(Trade::getIsDeleted, 0);
        wrapper.orderByDesc(Trade::getTradeDate);
        Page<Trade> tradePage = this.page(pageObj, wrapper);
        ArrayList<TradeVO> voList = new ArrayList<>();
        for (Trade trade : tradePage.getRecords()) {
            TradeVO vo = new TradeVO();
            BeanUtils.copyProperties(trade, vo);
            voList.add(vo);
        }
        PageResult<TradeVO> result = new PageResult<>();
        result.setTotal(tradePage.getTotal());
        result.setPage((int) tradePage.getCurrent());
        result.setSize((int) tradePage.getSize());
        result.setRecords(voList);
        return result;
    }

    @Override
    @Transactional
    public void transfer(TransferDTO transferDTO) {
        if (transferDTO == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "转账参数不能为空");
        }
        String fromCardId = transferDTO.getFromCardId();
        String toCardId = transferDTO.getToCardId();
        Double amount = transferDTO.getAmount();
        String password = transferDTO.getPassword();
        String remark = transferDTO.getRemark();
        
        // 验证卡号格式
        if (fromCardId == null || !fromCardId.matches("^\\d{16}$")) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "转出卡号格式错误，必须是16位数字");
        }
        if (toCardId == null || !toCardId.matches("^\\d{16}$")) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "转入卡号格式错误，必须是16位数字");
        }
        // 验证转账金额
        if (amount == null || amount < 1) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "单笔转账金额不能小于1元");
        }
        // 验证不能转给自己
        if (fromCardId.equals(toCardId)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "转出卡和转入卡不能是同一张卡");
        }
        //查询转出卡信息并验证权限
        Card fromCard = cardMapper.selectById(fromCardId);
        if (fromCard == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "转出卡不存在");
        }
        // 新增：挂失校验
        if (fromCard.getIsReportLoss() != null && fromCard.getIsReportLoss() == 1) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "转出卡已挂失，无法进行转账操作");
        }
        //验证权限
        User currentUser = UserHolder.getUser();
        if (!currentUser.getUserId().equals(fromCard.getUserId())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无权限操作此银行卡");
        }
        // 验证转出卡密码
        String passwordMd5 = MD5.create().digestHex(password);
        if (!passwordMd5.equals(fromCard.getPassword())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "转出卡密码错误");
        }
        //验证转出卡余额
        BigDecimal transferAmount = BigDecimal.valueOf(amount);
        BigDecimal requiredAmount = transferAmount.add(BigDecimal.ONE); // 转账金额+1元
        if (fromCard.getBalance().compareTo(requiredAmount) < 0) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "转出卡余额不足，需要≥转账金额+1元");
        }
        //查询转入卡信息并验证状态
        Card toCard = cardMapper.selectById(toCardId);
        if (toCard == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "转入卡不存在");
        }
        // 新增：挂失校验
        if (toCard.getIsReportLoss() != null && toCard.getIsReportLoss() == 1) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "转入卡已挂失，无法接收转账");
        }
        //执行转账操作
        //扣除转出卡余额
        fromCard.setBalance(fromCard.getBalance().subtract(transferAmount));
        fromCard.setUpdateTime(LocalDateTime.now());
        cardMapper.updateById(fromCard);
        
        // 增加转入卡余额
        toCard.setBalance(toCard.getBalance().add(transferAmount));
        toCard.setUpdateTime(LocalDateTime.now());
        cardMapper.updateById(toCard);
        
        //生成转账交易记录
        LocalDateTime now = LocalDateTime.now();
        
        // 转出记录
        Trade fromTrade = new Trade();
        fromTrade.setCardId(fromCardId);
        fromTrade.setTradeDate(now);
        fromTrade.setTradeType("支取");
        fromTrade.setTradeMoney(transferAmount);
        fromTrade.setRemark("转账给" + toCardId);
        fromTrade.setCreateTime(now);
        fromTrade.setUpdateTime(now);
        this.save(fromTrade);
        
        // 转入记录
        Trade toTrade = new Trade();
        toTrade.setCardId(toCardId);
        toTrade.setTradeDate(now);
        toTrade.setTradeType("存入");
        toTrade.setTradeMoney(transferAmount);
        toTrade.setRemark("转账来自" + fromCardId);
        toTrade.setCreateTime(now);
        toTrade.setUpdateTime(now);
        this.save(toTrade);
    }
} 